<!--
#
# Copyright 2010 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This code is not supported by Google
#
-->

<!--
Sample PHP code for Google Commerce Search to submit ShoppingAPI-Search queries 
then parse out the responses for display. Shows additive filtering, 
page navigation, spelling suggestions and promotions.

This code requires the php cURL module as well as Xpath support
--->

<?php
// Add &debug=1 to your query url to print the full Shopping API Request and other debugging info

// You can pass in devkey & cx parameters for testing, but for production use you
// should hardcode those parameters and not use them within the query parameters
// Get your Dev Key Here: https://code.google.com/apis/console/?api=shopping
if ($_REQUEST['devkey'] != "") { 
  $DEV_KEY = $_REQUEST['devkey'];
  $params .= "&devkey=$DEV_KEY";
 } else {
  $DEV_KEY = "<YOUR DEVELOPER KEY>";
 }

// CX ID is your Search engine unique ID from the GCS admin console:
// http://www.google.com/cse/commercesearch/manage
if ($_REQUEST['cx'] != "") {
  $CX = $_REQUEST['cx'];
  $params .= "&cx=$CX";
 } else {
  $CX = "016458501645884057912:dq_ixbwhuk8";  // Replace with your CX
 }

// List of facets we don't want to show up on the left
// Can also be controlled through "Facet Rules" in admin console
$IGNORE_FACETS = array('cpr_category','categoryid','product type', 'flags',
                       'product_ad_extension_trademark_cleared',
                       'product_ads_policy_cleared');

// You can manually select which facets to return - this option should be used
// in most production environments if possible
//$FACETS = "&facets.enabled=true&facets.include=category+name(text):20,price:10,brand(text):50,dimensions(text):5";

// OR you can have all the facets discovered (slower, less efficient)
$FACETS = "&facets.enabled=true&facets.useGcsConfig=true&facets.discover=20:10";

$BASE_URL = "https://www.googleapis.com/shopping/search/v1/cx:$CX/products".
  "?key=$DEV_KEY&country=US&language=en&alt=atom&spelling.enabled=true".
  "&safe=false&redirects.enabled=true&redirects.useGcsConfig=true".
  "&availability=outOfStock,backorder,inStock,limited".
  "&promotions.enabled=true&promotions.useGcsConfig=true$FACETS";

$RESULTS_PER_PAGE = 20;
$SCRIPT_NAME = "search.php";
$CURRENCY = '$';

// First Handle all the parameters that were passed in

$refinements = "";
$page = sprintf("%d", $_GET[page]);
if ($page == "" or $page == "0") {
  $page = 1;
}

$_GET[q] = preg_replace("/([^\d])\.([^\d])/","$1 $2",$_GET[q]);
$_GET[q] = trim(urldecode($_GET[q]));

$QUERYSTRING = preg_replace("/[\.,=#]/"," ", $_GET[q]);
$QUERYSTRING = preg_replace("/'/","", $QUERYSTRING);
$QUERYSTRING = preg_replace("/([^ ])[\-]/","$1 ", $QUERYSTRING);
$QUERYSTRING = urlencode($QUERYSTRING);

// Sorting
$sort = "";
if ($_REQUEST[rankBy] == "") {
  $sort .= "&rankBy=relevancy";
 } else {
  $sort .= "&rankBy=" . $_REQUEST[rankBy];
 }

// Restricts
if ($_REQUEST[restrict] != "") {
  foreach ($_REQUEST[restrict] as $restrict) {
    $refinements .= "$restrict,";
    $params .= "&restrict[]=$restrict";
  }
  $refinements = rtrim($refinements,",");
 }

if ($refinements != "") {
  $restrictby = "&restrictBy=$refinements";
  $restrictby = str_replace(" ","+",$restrictby);
 }

// Construct the request url
$url = sprintf("%s".
               "&startIndex=%d&maxResults=%d".
               "%s".
               "%s".
               "&q=%s",
               $BASE_URL,
               ((($page-1)* $RESULTS_PER_PAGE) + 1),
	       $RESULTS_PER_PAGE,
               $sort,
               $restrictby,
               $QUERYSTRING
               );


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);  //10 sec timeout
curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 100);
curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 10);

$return = curl_exec($ch);
$errno = curl_errno($ch);
curl_close($ch);

if ($_GET[debug] == 1) {
  print "$url<br>\n";
}

if ($errno && $_GET[debug] == 1) {
  print "Error: $errno<br>\n";
}

$xml = simplexml_load_string($return);
$result = $xml->xpath('//openSearch:totalResults');
$START = array_shift($xml->xpath('openSearch:startIndex'));
$RESULTS = array_shift($xml->xpath('openSearch:totalResults'));

// Check for Redirect
$REDIRECT_URL = array_shift($xml->xpath('s:redirects/s:redirect/@link'));
if ($REDIRECT_URL != "") {
  header("Location: $REDIRECT_URL",TRUE,301);
  exit();
 }

if ($RESULTS > 1000) {
  if ($RESULTS > 25000) {
    $BODY = "<center><b><i>Over 25,000 results found, showing the first 1000</i></b></center><br>";
  } else {
    $BODY = "<center><b><i>$RESULTS results found, showing the first 1000</i></b></center><br>";
  }

  $TOTALRESULTS = $RESULTS;
  $RESULTS = 1000;

} else if ($RESULTS == 0) {
  $BODY = sprintf("<br><br><br><center><font size=+1><b>No Results Found for search <i>%s</i></b></font></center>", $_GET[q]);
}

if ($RESULTS != 0) {
  // Sorting
  $REFINEMENT_PANEL .= "<b>Sort By:</b><br/>";
  if ($_REQUEST[rankBy] != "") {
    $REFINEMENT_PANEL .= 
      sprintf("&nbsp;<u><a href=\"$SCRIPT_NAME?q=%s%s\">Best Match</a></u><br/>",
	      urlencode($_GET[q]),
	      $params);
  } else {
    $REFINEMENT_PANEL .= "&nbsp;Best Match<br/>";
  }

  if ($_REQUEST[rankBy] != "price:ascending") {
    $REFINEMENT_PANEL .=
      sprintf("&nbsp;<a href=\"$SCRIPT_NAME?q=%s%s&rankBy=price:ascending\"><u>Price (Lowest first)</u></a><br/>",
	      urlencode($_GET[q]),
	      $params);
  } else {
    $REFINEMENT_PANEL .= "&nbsp;Price (Lowest first)<br/>";
  }

  if ($_REQUEST[rankBy] != "price:descending") {
    $REFINEMENT_PANEL .=
      sprintf("&nbsp;<a href=\"$SCRIPT_NAME?q=%s%s&rankBy=price:descending\"><u>Price (Highest first)</u></a><br/>",
	      urlencode($_GET[q]),
	      $params);
  } else {
    $REFINEMENT_PANEL .= "&nbsp;Price (Highest first)<br/>";
  }
  $REFINEMENT_PANEL .= "<br/>";

  if ($_REQUEST[rankBy] != "") {
    $params .= "&rankBy=$_GET[rankBy]";
  }
}


// Spelling Suggestions
$spelling_suggestion = array_shift($xml->xpath('s:spelling/s:suggestion'));

if ($spelling_suggestion != "") {
  $BODY .= 
    sprintf("<center><font size=+1><b>Did you mean: ".
	    "<i><a href=\"$SCRIPT_NAME?q=%s\"><font color=blue>%s</font></a>".
	    "</i></b></center>",
	    $spelling_suggestion, $spelling_suggestion);
 }


// Promotions, just displayed in a simple table at the top of search results for now
$promos = "";
foreach ($xml->xpath('s:promotions/*') as $item) {
  $promos .= "<td><a href='$item[link]'>$item[description]";
  if ($item[imageLink] != "") {
    $promos .= "<br/><img src='$item[imageLink]'>";
  }
  $promos .= "</td>";
}

if ($promos != "") {
  $BODY .= "<center><table><tr>$promos</tr></table></center>";
 }


// Parse through the items
$COL = 1;
$BODY .= "<TABLE width=100% align=center border=0>";
foreach ($xml->entry as $item) {
  $TITLE = $item->title;
  $PRICE = "$CURRENCY" . sprintf("%.2f",array_shift($item->xpath('s:product/s:attributes/s:attribute[@name="price"]')));

  $IMG_URL = array_shift($item->xpath('s:product/s:images/s:image/@link'));
  $URL = $item->link->attributes()->href;
  
  if (strlen($TITLE) > 60) {
    $TITLE = sprintf("%.60s...", $TITLE);
  }
  
  if ($COL == 1) {
    $BODY .= "<tr valign=top>";
  }

  $BODY .= 
    sprintf("<td width=\"25%%\" align=center valign=top>".
	    "<a href=\"%s\">".
	    "<img height=100 src=\"%s\" border=0></a><br>",
	    $URL,
	    $IMG_URL);
  
  $BODY .= sprintf("<font size=2><a href=\"%s\">%s</a></font><br/>%s",
		   $URL,$TITLE,$PRICE);
  $BODY .= "</td>\n";
  if ($COL == 4) {
    $BODY .= "</tr>";
    $COL = 1;
  } else {
    $COL++;
  }
}
if ($COL != 1) {
  $BODY .= "</tr>";
}
$BODY .= "</table>";

// Handle Attributes
$NARROW = "";
foreach ($xml->xpath('s:facets/*') as $item) {
  $values = $item->xpath('s:bucket');
  $type = $item['type'];
  $attrib_name = $item['name'];
  $display_name = $item['displayName'];
  if ($attrib_name == "") {
    $attrib_name = $item['property'];  // Default types
  }
  $units = $item['unit'];

  if (in_array($attrib_name, $IGNORE_FACETS)) {
    continue;
  }

  $NARROW .= "<b>$display_name:</b><br/>\n";
  foreach ($values as $value_item) {
    if ($type == "") {
      $link = "$attrib_name=";
    } else if ($units != "") {
      $link = "$attrib_name($type)/$units=";
    } else {
      $link = "$attrib_name($type)=";
    }

    $key = ucwords($value_item['value']);
    if ($key == "") { // We've got range buckets
      if ($attrib_name == "price") {
	$denom = $CURRENCY;
	$units = "";
	// Change %d to %.2f if you need decimal places for prices
	$min = sprintf("%d",$value_item['min']);
	$max = sprintf("%d",$value_item['max']);
	$min_e = sprintf("%d",$value_item['minExclusive']);
	$max_e = sprintf("%d",$value_item['maxExclusive']);
      } else {
	$denom = "";
	$min = $value_item['min'];
	$max = $value_item['max'];
	$min_e = $value_item['minExclusive'];
	$max_e = $value_item['maxExclusive'];
      }

      if ($min != "0" and $min != "" and $max != "0" and $max != "") {
	$key = "$denom$min to $denom$max$units";
      }
      
      if ($min == "0" or $min == "") {
	$key = "Up to $denom$max$units";
	$min = "*";
      }
      
      if ($max == "0" or $max == "") {
	$key = "Over $denom$min$units";
	$max = "*";
      }
      if ($min_e == 'true') {
	$link .= "(";
      } else {
	$link .= "[";
      }
      $link .= "$min,$max";

      if ($max_e == 'true') {
        $link .= ")";
      } else {
        $link .= "]";
      }
    } else {
      $link .= $key;
    }

    $value = (int)$value_item['count'];
    $NARROW .=
      sprintf("<u><a href=\"$SCRIPT_NAME?q=%s%s&restrict[]=%s\">%s</a></u> (%d)<br/>",
	      urlencode($_GET[q]),
	      $params,
	      $link,
	      $key,
	      $value);
  }

  if (preg_match("/$attrib_name/",$refinements)) {
    $NARROW .= sprintf("&nbsp;<u><a href=\"$SCRIPT_NAME?q=%s%s\">View All</a></u><br/>",
		       urlencode($_GET[q]),
		       $sub_params);

  }
  $NARROW .= "<br/>";
}

$REFINEMENT_PANEL .= $NARROW;

$TOTALPAGES = ceil($RESULTS/$RESULTS_PER_PAGE);
$pagenav_url = sprintf("$SCRIPT_NAME?q=%s%s&page=%%d",
		       urlencode($_GET[q]),
		       $params);
?>

<html>
<head>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
  //<![CDATA[

  // For Search-As-You-Type Autocomplete
  google.load('search', '1');
function onLoad() {
  google.search.CustomSearchControl.attachAutoCompletion('<?= $CX; ?>',
                                                         document.getElementById('searchText'),
                                                         'search-form');
}

google.setOnLoadCallback(onLoad);
//]]>
</script>

<!-- link type="text/css" rel="stylesheet" href="http://www.google.com/products/intl/en_us/css/ps-style.css" -->
<style type="text/css">
#pagenav a, #pagenav .current, #pagenav .inactive {
  font-size: 11px;  padding: 2px 5px 2px 5px;  margin: 0px 1px 0px 1px;
border: 1px solid #fff; background: #fff; display:block; color: #304685;
}
#pagenav .current {
border: 1px solid #304685;  font-weight: bold;  background: #304685;
color: #fff;
}
#pagenav .inactive {
border: 1px solid #aaa;  font-weight: normal;  background: #fff; color: #aaa;
}
#pagenav a {
border: 1px solid #9aafe5; text-decoration: none; color: #304685;
}

#pagenav a:hover {
border-color: #9aafe5; background: #304685; color: #fff;
}
</style>
</head>
<body>
<img src="http://www.google.com/images/logos/commerce_search_logo.gif"><br/>
<form name="searchform" id="search-form" method="GET">
<input id="searchText" type="text" name="q" value="<?=$_GET[q]?>" autocomplete="off">
<input type=submit value="Search">
    <?php if ($_REQUEST['cx'] != "") { ?>
<input type="hidden" name="cx" value="<?= $_REQUEST['cx'] ?>">
				    <?php } ?>
				    <?php if ($_REQUEST['devkey'] != "") { ?>
<input type="hidden" name="devkey" value="<?= $_REQUEST['devkey'] ?>">
      <?php } ?>
</form>
<hr width="100%" size=1>

<table>
<tr>
<td valign=top><?=$REFINEMENT_PANEL?></td>
<td valign=top width=800>
  <?php display_pagenav() ?>
<?=$BODY?></td>
</tr>
</table>

</body>
</html>

<?php 
function display_pagenav() {
  global $TOTALPAGES, $page, $pagenav_url;
// Page navigation..
// To use set variable $pagenav_url with value of target url
// use %d where target page number should be replaced in target url string.

  if (!$NAVSIZE) { $NAVSIZE = 10;}
  if ($TOTALPAGES>1) {

    print "<div align=center><table border=0 cellspacing=0 cellpadding=0 id=pagenav><tr><td>";

    if ($page > 1) {
      printf("<a href=\"$pagenav_url\" class=\"nextprev\" title=\"Go to Previous Page\"><b>&#171;&nbsp;Previous</b></a></td><td>", $page-1);
    } else {
      print "<div class=inactive>&#171; Previous</div></td><td>";
    }
    
    if ($TOTALPAGES>$NAVSIZE) {
      if ($page<=$NAVSIZE/2) {
	for ($j=1; $j<=$NAVSIZE; $j++) {
	  if ($j==$page) {
	    print "<div class=current>$j</div></td><td>";
	  } else {
	    printf("<a href=\"$pagenav_url\" title=\"Go to page $j\">$j</a></td><td>", $j);
	  }
	  
	}
	printf("<div class=dots>...</div></td><td><a href=\"$pagenav_url\" title=\"Go to page $TOTALPAGES\">".$TOTALPAGES."</a></td><td>",$TOTALPAGES);
	
      } else if (($TOTALPAGES-$page)<=$NAVSIZE/2) {
	printf("<a href=\"$pagenav_url\" title=\"Go to page 1\">1</a></td><td><div class=dots>...</div></td><td>",1);
	for ($j=$TOTALPAGES-$NAVSIZE; $j<=$TOTALPAGES; $j++) {
	  if ($j==$page) {
	    print "<div class=current>$j</div></td><td>";
	  } else {
	    printf("<a href=\"$pagenav_url\" title=\"Go to page $j\">$j</a></td><td>",$j);
	  }
	}
      } else {
	printf("<a href=\"$pagenav_url\" title=\"Go to page 1\">1</a></td><td><div class=dots>...</div></td><td>",1);
	for ($j=($page-($NAVSIZE/2)+1); $j<=($page+$NAVSIZE/2); $j++) {
	  if ($j==$page) {
	    print "<div class=current>$j</div></td><td>";
	  } else {
	    printf("<a href=\"$pagenav_url\" title=\"Go to page $j\">$j</a></td><td>",$j);
	  }
	  
	}
	printf("<div class=dots>...</div></td><td><a href=\"$pagenav_url\" title=\"Go to page $TOTALPAGES\">".$TOTALPAGES."</a></td><td>",$TOTALPAGES);
      }
      
    }  else {
      for ($j=1; $j<=$TOTALPAGES; $j++) {
	if ($j==$page) {
	  print "<div class=current>$j</div></td><td>";
	} else {
	  printf("<a href=\"$pagenav_url\" title=\"Go to page $j\">$j</a></td><td>",$j);
	}
      }
    }

    if ($page < $TOTALPAGES) {
      printf("<a href=\"$pagenav_url\" title=\"Go to Next Page\"><b>Next&nbsp;&#187;</b></a></td><td>",$page+1);
    } else {
      print "<div class=inactive>Next &#187;</div></td><td>";
    }

  print "</td></tr></table></div>";

  } else {
  // No results in recordset, don't display nav..
  }
}
?>